package edu.hawaii.myisern.model;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.List;
import org.junit.After;
import org.junit.Test;

/**
 * Test the MyIsernDatabase.
 * 
 * @author Randy Cox
 * 
 */
public class TestDatabaseOrganizations {

  /**
   * Test the dropping and creating of organization tables.
   */
  @Test
  public void testCreateDropTable() {
    DatabaseOrganizations db = new DatabaseOrganizations();
    db.createTables();
    assertTrue("Check that organization table is there.", db.hasTableOrganization());
    assertTrue("Check that affiliated researcher table is there.", db.hasTableAfResearchers());
    db.createTables();
    assertTrue("Check that organization table is still there.", db.hasTableOrganization());
    assertTrue("Check that aff researcher table is still there.", db.hasTableAfResearchers());
    db.dropTables();
    assertFalse("Check that organization table is gone.", db.hasTableOrganization());
    assertFalse("Check that affiliated researcher table is gone.", db.hasTableAfResearchers());
    db.dropTables();
    assertFalse("Check that there is no error.", db.hasTableOrganization());
    assertFalse("Check that there is no error with sub table.", db.hasTableAfResearchers());
  }

  /**
   * Test the insert, update, query etc for the organization table.
   */
  @Test
  public void testGetSave() {
    DatabaseOrganizations db = new DatabaseOrganizations();

    // Set up test strings.
    String id = ("ORGANIZATION");
    String name = "Organization";
    String type = "Type";
    String contact = "Contact";
    String[] researchers = { "Researcher1", "Researcher2", "Researcher3" };
    String country = "Country";
    String[] keywords = { "Keyword1", "Keyword2", "Keyword3" };
    String description = "Description";
    String homePage = "Home Page";

    // Set up record vars.
    MyOrganization organization = new MyOrganization();
    organization.setName(name);
    organization.setType(type);
    organization.setContact(contact);
    organization.addAffiliatedResearcher(researchers[0]);
    organization.addAffiliatedResearcher(researchers[1]);
    organization.addAffiliatedResearcher(researchers[2]);
    organization.setCountry(country);
    organization.addResearchKeyword(keywords[0]);
    organization.addResearchKeyword(keywords[1]);
    organization.addResearchKeyword(keywords[2]);
    organization.setResearchDescription(description);
    organization.setHomePage(homePage);

    // Save organization and check count.
    db.save(organization);
    assertTrue("Check if organization found after save.", db.hasOrganization(id));

    // Retrieve organization back and check values.
    MyOrganization organization2 = db.get(id);
    assertEquals("Check ID2.", id, organization2.getId());
    assertEquals("Check name2.", name, organization2.getName());
    assertEquals("Check type2.", type, organization2.getType());
    assertEquals("Check contact2.", contact, organization2.getContact());
    assertEquals("Check res2-1.", researchers[0], organization2.getAffiliatedResearchers().get(0));
    assertEquals("Check res2-2.", researchers[1], organization2.getAffiliatedResearchers().get(1));
    assertEquals("Check res2-3.", researchers[2], organization2.getAffiliatedResearchers().get(2));
    assertEquals("Check country2.", country, organization2.getCountry());
    assertEquals("Check keyword2-1.", keywords[0], organization2.getResearchKeywords().get(0));
    assertEquals("Check keyword2-2.", keywords[1], organization2.getResearchKeywords().get(1));
    assertEquals("Check keyword2-3.", keywords[2], organization2.getResearchKeywords().get(2));
    assertEquals("Check descripiton2.", description, organization2.getResearchDescription());
    assertEquals("Check homepage2.", homePage, organization2.getHomePage());

    // Test for non-existent organization.
    assertFalse("Check non-existant organization.", db.hasOrganization("BAD_ID"));
    assertNull("Check getting non-existant organization.", db.get("BAD_ID2"));

    // Test update.
    db.save(organization);
    assertTrue("Check if organization found after save.", db.hasOrganization(id));

    // Retrieve organization back and check values.
    MyOrganization organization3 = db.get(id);
    assertEquals("Check ID3.", id, organization3.getId());
    assertEquals("Check name3.", name, organization3.getName());
    assertEquals("Check type3.", type, organization3.getType());
    assertEquals("Check contact3.", contact, organization3.getContact());
    assertEquals("Check res3-1.", researchers[0], organization3.getAffiliatedResearchers().get(0));
    assertEquals("Check res3-2.", researchers[1], organization3.getAffiliatedResearchers().get(1));
    assertEquals("Check res3-3.", researchers[2], organization3.getAffiliatedResearchers().get(2));
    assertEquals("Check country3.", country, organization3.getCountry());
    assertEquals("Check keyword3-1.", keywords[0], organization3.getResearchKeywords().get(0));
    assertEquals("Check keyword3-2.", keywords[1], organization3.getResearchKeywords().get(1));
    assertEquals("Check keyword3-3.", keywords[2], organization3.getResearchKeywords().get(2));
    assertEquals("Check descripiton3.", description, organization3.getResearchDescription());
    assertEquals("Check homepage3.", homePage, organization3.getHomePage());
  }

  /**
   * Test the insert, update, query etc for the organization table.
   */
  @Test
  public void testClearDeleteListCount() {
    DatabaseOrganizations db = new DatabaseOrganizations();
    db.clear();

    // Set up test strings.
    String name = "Organization Name ";
    String type = "Type";
    String contact = "Contact";
    String[] researchers = { "Researcher1", "Researcher2", "Researcher3" };
    String country = "Country";
    String[] keywords = { "Keyword1", "Keyword2", "Keyword3" };
    String description = "Description";
    String homePage = "Home Page";

    // Set up record vars.
    MyOrganization organization = new MyOrganization();
    organization.setName(name);
    organization.setType(type);
    organization.setContact(contact);
    organization.addAffiliatedResearcher(researchers[0]);
    organization.addAffiliatedResearcher(researchers[1]);
    organization.addAffiliatedResearcher(researchers[2]);
    organization.setCountry(country);
    organization.addResearchKeyword(keywords[0]);
    organization.addResearchKeyword(keywords[1]);
    organization.addResearchKeyword(keywords[2]);
    organization.setResearchDescription(description);
    organization.setHomePage(homePage);

    // Save organization and check count.
    Integer expected = 0;
    assertEquals("Check that db is empty.", expected, db.count());
    organization.setName("name1");
    db.save(organization);
    expected++;
    assertEquals("Check that db has 1 record.", expected, db.count());

    // Save 2nd record
    organization.setName("name2");
    db.save(organization);
    expected++;
    assertEquals("Check that db has 2 records.", expected, db.count());

    // Save 3rd record
    organization.setName("name3");
    db.save(organization);
    expected++;
    assertEquals("Check that db has 3 records.", expected, db.count());

    // Check list function
    List<MyOrganization> results = db.list();
    assertEquals("Check record 1", "NAME1", results.get(0).getId());
    assertEquals("Check record 2", "NAME2", results.get(1).getId());
    assertEquals("Check record 3", "NAME3", results.get(2).getId());

    // Delete 2nd record
    organization.setName("name2");
    db.delete("NAME2");
    expected--;
    assertEquals("Check that db has 2 records.", expected, db.count());
    assertFalse("Check that record 2 is gone", db.hasOrganization("NAME2"));

    db.clear();
    expected = 0;
    assertEquals("Check that db is empty.", expected, db.count());
  }

  /**
   * Drop test tables.
   */
  @After
  public void cleanUpTables() {
    DatabaseOrganizations db = new DatabaseOrganizations();
    db.dropTables();
  }

}
